import java.util.ArrayList;
import java.util.List;

/**
 * Player class. Each Player has five ships, and a list of cells they have
 * attacked. A Player can determine whether he or she has been defeated or not.
 */
public class Player {
	/**
	 * An array containing the five ships a player owns.
	 */
	private Ship[] ships;
	/**
	 * An array of cell positions that the player has attacked.
	 */
	private List<String> used;
	/**
	 * An array containing all the cells that a player's ships occupy.
	 */
	private List<String> allShips;

	/**
	 * Default constructor of the player, which constructs their ships, and
	 * allocates space in memory for the cells the player attacks and the ships
	 * occupied cells.
	 */
	public Player() {
		ships = new Ship[] { new AircraftCarrier(), new Battleship(),
				new Cruiser(), new Submarine(), new Destroyer() };
		used = new ArrayList<String>();
		allShips = new ArrayList<String>();
	}

	/**
	 * @return The array of this player's ships. The array must always contain
	 *         the ships in this order: AircraftCarrier, Battleship, Cruiser,
	 *         Submarine, and Destroyer.
	 */
	public final Ship[] getShips() {
		return ships;
	}

	/**
	 * @return The array of all cells that the ships this player owns occupies.
	 */
	public final List<String> getShipCells() {
		return allShips;
	}

	/**
	 * @return The array of all cells that the player has clicked on the
	 *         opposing player's grid.
	 */
	public final List<String> getUsedCells() {
		return used;
	}

	/**
	 * Returns true if this player has been defeated when all ships owned by the
	 * player are verified to be sunk.
	 * 
	 * @return Returns true if this player has been defeated, false otherwise.
	 */
	public final Boolean isDefeated() {
		int sunkCount = 0;
		for (int i = 0; i < ships.length; i++) {
			if (ships[i].isSunk()) {
				sunkCount++;
			}
		}
		return sunkCount == ships.length;
	}

	/**
	 * Adds a single cell referencing a location on the opposing player's grid
	 * to the array of cells that this player has attacked.
	 * 
	 * @param cell
	 *            The cell the player has most recently attacked.
	 */
	public final void addAttackedCell(String cell) {
		used.add(cell);
	}

	/**
	 * Checks the cell the player is trying to attack with the list of already
	 * attacked positions. If the cell has already been attacked, return false.
	 * Otherwise, the attack is valid and return true.
	 * 
	 * @param cell
	 *            The cell the player is trying to attack.
	 * @return Returns whether or not a player's attack has been attempted
	 *         before.
	 */
	public final Boolean isValidAttack(String cell) {
		boolean answer = false;
		if (!used.contains(cell)) {
			answer = true;
		}
		return answer;
	}

	/**
	 * Determines whether or not the selected cell, targeted by the opposing
	 * player, contains one of this player's ships.
	 * 
	 * @param cell
	 *            The cell that is checked for ship occupation.
	 * @return Whether or not the selected cell hits one of this player's ships
	 *         or not.
	 */
	public final Boolean isHit(String cell) {
		boolean answer = false;
		for (Ship s : ships) {
			if (s.getCells().contains(cell)) {
				answer = true;
				s.hit();
				allShips.remove(cell);
			}
		}
		return answer;
	}
}
